package com.david.equipment.service.impl;

import com.david.equipment.common.constant.TacticsItemResult;
import com.david.equipment.mapper.TacticsMapper;
import com.david.equipment.pojo.entity.*;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Transactional;

import java.time.LocalDate;
import java.time.format.DateTimeFormatter;
import java.util.ArrayList;
import java.util.List;
import java.util.Objects;

@Component
@Slf4j
public class TacticsCronTask {
    @Autowired
    private TacticsMapper tacticsMapper;

    // 每日任务更新
    @Scheduled(cron = "0 53 13 1/1 * ?")
//    @Scheduled(fixedDelay = 100000)
    public void dailyTask() {
        log.info("开启定时任务 >>>>>>> 生成每日策略任务");
        // 查询status为1的任务
        TacticsEntity tacticsEntity = new TacticsEntity();
        tacticsEntity.setStatus("1");
        List<TacticsEntity> tacticsEntities = tacticsMapper.selectTactics(tacticsEntity);
        // 生成待办任务,
        for (TacticsEntity tactics : tacticsEntities){
            List<TacticsDevice> devicelist = tacticsMapper.selectTacticsDevices(tactics.getId(),"1");
            if (!devicelist.isEmpty()){
//                判断循环周期是否是在今日
                boolean isToday = false;
                if (LocalDate.now().isBefore(tactics.getStartDate()) || tactics.getProjectId() == null){
                    break;
                } else {
                    if (tactics.getEndDate() != null && LocalDate.now().isAfter(tactics.getEndDate())) {
                        break;
                    }
                    String loopUnit = tactics.getLoopPeriod().substring(tactics.getLoopPeriod().length() - 1);
                    int loopNum = Integer.parseInt(tactics.getLoopPeriod().substring(0, tactics.getLoopPeriod().length() - 1));
                    isToday = switch (loopUnit) {
                        case "D" ->
                            // 循环单位为天，则生成任务
                                tactics.getStartDate().until(LocalDate.now()).getDays() % loopNum == 0;
                        case "W" ->
                            // 循环单位为周，则生成任务
                                LocalDate.now().getDayOfWeek().getValue() == loopNum;
                        case "M" ->
                            // 循环单位为月，则生成任务
                                LocalDate.now().getDayOfMonth() == loopNum;
                        default -> false;
                    };
                }
//                不是今日的直接break循环
                if(!isToday) break;
//                今日有任务的才进行生成任务处理
                //生成任务CODE
                String taskCode = tactics.getCode().concat("-").concat(LocalDate.now().format(DateTimeFormatter.ofPattern("yyMMdd")));

                //复制策略信息，并在task表中增加taskID信息
                TacticsTaskEntity task = TacticsTaskEntity.builder()
                        .tacticsId(tactics.getId())
                        .tacticsName(tactics.getName())
                        .code(taskCode)
                        .deptId(tactics.getDeptId())
                        .startDate(LocalDate.now())
                        .endDate(LocalDate.now().plusDays(tactics.getDuration()))
                        .build();
                tacticsMapper.insertTask(task);
//                获取projectID对应的items
                List<TacticsProjectItems> items = tacticsMapper.selectItems(tactics.getProjectId());
                //复制设备信息及关联表，并在task_device表中增加taskID信息
                for (TacticsDevice device : devicelist){
                    TacticsTaskDeviceEntity taskDevice = TacticsTaskDeviceEntity.builder()
                            .deviceId(device.getDeviceId())
                            .taskId(task.getId())
                            .remark(device.getRemark())
                            .build();
                    tacticsMapper.insertTacticsTaskDevices(taskDevice);
                    for (TacticsProjectItems item : items){
                        TacticsTaskItems taskItem = TacticsTaskItems.builder()
                                .taskId(task.getId())
                                .deviceId(device.getDeviceId())
                                .name(item.getName())
                                .content(item.getContent())
                                .remark(item.getRemark())
                                .build();
                        tacticsMapper.insertTacticsTaskItems(taskItem);
                    }
                }
            }
            log.info("结束定时任务 <<<<<<<< 生成每日策略任务");
        }
    }

    // 每日任务归档，完成的任务完成时转至history表中，未完成的自动归档
    // 正常的任务，在完成时即已归档，查询到超时的任务均为未完成的。
    @Scheduled(cron = "0 0 1 1/1 * ?")
//    @Scheduled(fixedDelay = 100000)
    @Transactional(rollbackFor = Exception.class)
    public void dailyTaskArchive() {
        log.info("开启定时任务 <<<<<<<< 归集每日策略任务");
        // task的三张表中，task-device关联表的相关内容直接删除即可，task和items的信息完善后移至history表中
        //第一步， 查询task表中超时的任务
        LocalDate now = LocalDate.now();
        List<TacticsTaskEntity> taskEntities = tacticsMapper.selectTacticsTaskOutTime(now);
        if (taskEntities.isEmpty()){
            return;
        }
        for (TacticsTaskEntity task : taskEntities){
            // 每个预设任务转化为historyTask
            TacticsHisTaskEntity hisTask = TacticsHisTaskEntity.builder()
                    .completed("0")
                    .tacticsId(task.getTacticsId())
                    .tacticsName(task.getTacticsName())
                    .taskId(task.getId())
                    .code(task.getCode())
                    .deptId(task.getDeptId())
                    .startDate(task.getStartDate())
                    .endDate(task.getEndDate())
                    .build();
            TacticsTaskDeviceEntity taskDevice = TacticsTaskDeviceEntity.builder().taskId(task.getId()).build();
            // 查询当前任务对应的设备列表
            List<TacticsTaskDeviceEntity> taskdeviceEntities = tacticsMapper.selectTacticsTaskDevices(taskDevice);
            for (TacticsTaskDeviceEntity taskdevice : taskdeviceEntities){
                // 任务中的每个设备，完成任务中细化为每个设备,插入任务ID和设备ID对应的items
                TacticsTaskItems taskItem = TacticsTaskItems.builder()
                        .taskId(taskdevice.getTaskId())
                        .deviceId(taskdevice.getDeviceId())
                        .build();
                List<TacticsTaskItems> taskItems = tacticsMapper.selectTacticsTaskItems(taskItem);
                if (taskItems.isEmpty()){
                    break;
                }
                taskItems.forEach(taskitem -> {taskitem.setResult(TacticsItemResult.UNCOMPLETED.getRemark());});
                List<TacticsHisTaskItems> hisTaskItems = new ArrayList<>();
                for (TacticsTaskItems item : taskItems){
                    TacticsHisTaskItems hisTaskItem = new TacticsHisTaskItems();
                    BeanUtils.copyProperties(item, hisTaskItems);
                    hisTaskItems.add(hisTaskItem);
                }

                tacticsMapper.insertTacticsHisItems(hisTaskItems);

                // 查询任务项目，如果项目中有异常，则该任务为异常
                TacticsTaskItems hisItem = TacticsTaskItems.builder().taskId(task.getId()).build();
                List<TacticsTaskItems> hisTaskitemsList = tacticsMapper.selectTacticsHisItems(hisItem);
                for (TacticsTaskItems item : hisTaskitemsList){
                    if (Objects.equals(item.getResult(), TacticsItemResult.ABNORMAL.getRemark())) {
                        hisTask.setResult(TacticsItemResult.ABNORMAL.getRemark());
                        break;
                    } else {
                        hisTask.setResult(TacticsItemResult.UNCOMPLETED.getRemark());
                    }
                }
                hisTask.setDeviceId(taskdevice.getDeviceId());
                tacticsMapper.insertTacticsHisTask(hisTask);
            }
            // 清除task相关表中的数据
            tacticsMapper.deleteTacticsTaskItems(task.getId());
            tacticsMapper.deleteTacticsTaskDevice(task.getId());
            tacticsMapper.deleteTacticsTask(task.getId());

        }
        log.info("结束定时任务 <<<<<<<< 归集每日策略任务");
    }

}
